package com.dci.intellij.dbn2.browser.ui;

import com.dci.intellij.dbn.browser.model.BrowserTreeNode;
import com.dci.intellij.dbn.common.dispose.Disposable;
import com.dci.intellij.dbn.common.dispose.Nullifiable;
import com.dci.intellij.dbn.connection.ConnectionBundle;
import com.dci.intellij.dbn.connection.ConnectionHandler;
import com.dci.intellij.dbn.object.common.DBObject;
import com.dci.intellij.dbn.object.common.DBObjectBundle;
import com.intellij.ui.SpeedSearchBase;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreePath;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@Nullifiable
public class DatabaseBrowserTreeSpeedSearch extends SpeedSearchBase<JTree> implements Disposable {
    private static final Object[] EMPTY_ARRAY = new Object[0];
    private Object[] elements = null;
    private TreeModelListener treeModelListener = new TreeModelListener() {
        public void treeNodesChanged(TreeModelEvent e) {
            DatabaseBrowserTreeSpeedSearch.this.elements = null;
        }

        public void treeNodesInserted(TreeModelEvent e) {
            DatabaseBrowserTreeSpeedSearch.this.elements = null;
        }

        public void treeNodesRemoved(TreeModelEvent e) {
            DatabaseBrowserTreeSpeedSearch.this.elements = null;
        }

        public void treeStructureChanged(TreeModelEvent e) {
            DatabaseBrowserTreeSpeedSearch.this.elements = null;
        }
    };
    private boolean disposed;

    DatabaseBrowserTreeSpeedSearch(DatabaseBrowserTree tree) {
        super(tree);
        this.getComponent().getModel().addTreeModelListener(this.treeModelListener);
    }

    protected int getSelectedIndex() {
        Object[] elements = this.getAllElements();
        BrowserTreeNode treeNode = this.getSelectedTreeElement();
        if (treeNode != null) {
            for(int i = 0; i < elements.length; ++i) {
                if (treeNode == elements[i]) {
                    return i;
                }
            }
        }

        return -1;
    }

    private BrowserTreeNode getSelectedTreeElement() {
        TreePath selectionPath = this.getComponent().getSelectionPath();
        return selectionPath != null ? (BrowserTreeNode)selectionPath.getLastPathComponent() : null;
    }

    @NotNull
    protected Object[] getAllElements() {
        if (this.elements == null) {
            List<BrowserTreeNode> nodes = new ArrayList();
            BrowserTreeNode root = this.getComponent().getModel().getRoot();
            loadElements(nodes, root);
            this.elements = nodes.toArray();
        }

        return this.elements;
    }

    private static void loadElements(List<BrowserTreeNode> nodes, BrowserTreeNode browserTreeNode) {
        if (browserTreeNode.isTreeStructureLoaded()) {
            BrowserTreeNode treeNode;
            if (browserTreeNode instanceof ConnectionBundle) {
                ConnectionBundle connectionBundle = (ConnectionBundle)browserTreeNode;
                Iterator var3 = connectionBundle.getConnectionHandlers().iterator();

                while(var3.hasNext()) {
                    ConnectionHandler connectionHandler = (ConnectionHandler)var3.next();
                    DBObjectBundle objectBundle = connectionHandler.getObjectBundle();
                    loadElements(nodes, objectBundle);
                }
            } else {
                for(Iterator var6 = browserTreeNode.getChildren().iterator(); var6.hasNext(); loadElements(nodes, treeNode)) {
                    treeNode = (BrowserTreeNode)var6.next();
                    if (treeNode instanceof DBObject) {
                        nodes.add(treeNode);
                    }
                }
            }
        }

    }

    public DatabaseBrowserTree getComponent() {
        return (DatabaseBrowserTree)super.getComponent();
    }

    protected String getElementText(Object o) {
        BrowserTreeNode treeNode = (BrowserTreeNode)o;
        return treeNode.getPresentableText();
    }

    protected void selectElement(Object o, String s) {
        BrowserTreeNode treeNode = (BrowserTreeNode)o;
        this.getComponent().selectElement(treeNode, false);
    }

    public final boolean isDisposed() {
        return this.disposed;
    }

    public final void markDisposed() {
        this.disposed = true;
    }

    public void disposeInner() {
        this.getComponent().getModel().removeTreeModelListener(this.treeModelListener);
        this.elements = EMPTY_ARRAY;
        if (!this.isDisposed()) {
            this.markDisposed();
            this.disposeInner();
        }
    }
}
